#pragma once

#include "SRModel.h"
#include <vector>
#include <string>

namespace sora
{
	class DrawCommand;
	class ObjModel;
	class MeshModelBuilder;

	enum ObjNodeKeyword {
		//무의미한 데이터인 경우(주석, 엔터..)
		ObjNodeKeywordNull,

		//vertex data
		ObjNodeKeywordGeometricVertex,
		ObjNodeKeywordTextureVertex,
		ObjNodeKeywordVertexNormal,
		ObjNodeKeywordParameterSpaceVertex,

		//free-form curve-surface attribue

		//elements
		ObjNodeKeywordPoint,
		ObjNodeKeywordLine,
		ObjNodeKeywordFace,
		ObjNodeKeywordCurve,
		ObjNodeKeywordCurve2d,
		ObjNodeKeywordSurface,

		//free-form curve/surface body statement

		//connectivity between freeo-form surface

		//grouping
		ObjNodeKeywordGroupName,

		//display/render attribute
		ObjNodeKeywordMaterialName,
		ObjNodeKeywordMaterialLibrary,
	};

	enum ObjNodeCategory {
		ObjNodeCategoryVertexData,
		ObjNodeCategoryFreeformCurveSurfaceAttribute,
		ObjNodeCategoryElement,
		ObjNodeCategoryFreeformCurveSurfaceBodyStatement,
		ObjNodeCategoryConnectivityBetweenFreeformSurface,
		ObjNodeCategoryGrouping,
		ObjNodeCategoryDisplayRenderAttribute,
	};

	class ObjModel : public Model {
	public:
		//static
		static ObjNodeKeyword str2keyword(const std::string &value);
		static ObjNodeCategory str2category(ObjNodeKeyword keyword);
		static ObjNodeCategory str2category(const std::string &value);
	};

	class ObjNodeData {
	public:
		ObjNodeData();
		ObjNodeData(const std::string &line);
		~ObjNodeData();

		void reset();
		ObjNodeKeyword keyword() const;
		ObjNodeCategory category() const;

		const std::vector<std::string> &strList() const;
		const std::string &str(int index) const;
		int strCnt() const;

		const std::vector<int> &intList() const;
		int intValue(int index) const;
		int intCnt() const;

		static void destroy(std::vector<ObjNodeData*> datalist);

		//element 모드에서 필요한것
		int numVertex() const;
		int singleVertexNeedInt() const;	//1개의 vertex를 찍기위해서 필요한 점의 갯수
		std::vector<int> vertexInfo(int index) const;

		int vertex(int index) const;
		int tex(int index) const;
		int normal(int index) const;
	
	public:
		union {
			//vertex data경우 쓸것
			struct {
				float value[4];
				int valueCnt;
			};
			//element 용
			struct {
				bool useTex;
				bool useNormal;
			};
		};

	private:
		//복사 금지
		ObjNodeData(const ObjNodeData &other);
		//ObjNodeData &operator=(const ObjNodeData &data);

		ObjNodeKeyword keyword_;
		
		//문자열은 union에 못들어간다. 근데 문자열을 쓰는곳이 있으니까
		//문자열 저장공간을 좀 생성해놓자. type에 따라서 갖다쓰기
		std::vector<std::string> strList_;
		//element에서 사용되는 인덱스자체를 통짜로 저장.
		//tex, normal의 사용유무는 union에서 정의했으므로 한번에 몇개를 꺼내서
		//vertex로 구셩해야되는지는 알수있으므로 이것만 저장해도 일단은 충분하다
		std::vector<int> intList_;

		//friend class list
		friend class ObjNodeState;

		friend class ObjNodeCategoryVertexDataState;
		friend class ObjNodeVertexNormalState;
		friend class ObjNodeGeometricVertexState;
		friend class ObjNodeTextureVertexState;
		friend class ObjNodeParameterSpaceVertexState;

		friend class ObjNodeCategoryElementState;
		friend class ObjNodeFaceState;

		friend class ObjNodeCategoryDisplayRenderAttributeState;
		friend class ObjNodeMaterialNameState;
		friend class ObjNodeMaterialLibraryState;

		friend class ObjNodeCategoryGroupingState;
		friend class ObjNodeGroupNameState;
	};
}
